
// 名词解释：
// 框架：cacheflex开发框架
// 框架使用者：使用cache存储数据的人员，不关心cache内部实现
// 框架开发者：实现框架开发接口，定制框架特性的开发人员，可以重载index/reclaim/store三大主要模块的实现

////////////////////////////////////////////////////////////////////////////////////////////////////

// 框架为使用者提供的API：

class CacheAPI
{
  public:
    typedef void (*scan_callback_pt) (void *key, void *value, void *args);
  public:
    int init(InterfaceCacheUtils *cache_utils);
    int put(void *key, void *value, const int overwrite_key, const int overwrite_value);
    int get(void *key, void **value, RefHandle *ref_handle);
    void deref(RefHandle *ref_handle);
    int erase(void *key);
    int scan(scan_callback_pt scan_callback, void *args);
};

// 框架使用者需要实现的接口：
// 不实现时调用默认函数

class InterfaceCacheUtils
{
  public:
    virtual int64_t sizeof_key(void *key) = 0;
    virtual void *copy_key(void *key, void *buffer) = 0;
    virtual void *destroy_key(void *key) = 0;
    virtual int64_t sizeof_value(void *value) = 0;
    virtual void *copy_value(void *value, void *buffer) = 0;
    virtual void *destroy_value(void *value) = 0;
    virtual int64_t hash_key(void *key) = 0;
    virtual int compare_key(void *a, void *b) = 0;
};

////////////////////////////////////////////////////////////////////////////////////////////////////

// 下面是框架为开发者提供的API：

// 框架为每个key-value维护一个ItemHandle
//
// zyh: 我是不是可以理解成我们让Itemhandle做各个模块之间传递item时的标准？
//
// 注意多个item可能拥有同一个store_handle和reclaim_handle
//
//
// zyh: 名词解释:
// store_handle是store模块操作的最小单位的句柄, reclaim_handle是reclaim模块操作的最小单位的句柄
// 目前我们规定reclaim_handle的物理粒度小于等于store_handle的粒度
// 例如,一次alloc最少分配4kb内存, 而每个value为1kb,则一个合法的store_handle是0xfffff000,它对应的
// 可能reclaim_handle值是0xfffff000, 0xfffff400,0xfffff800,0xfffffc00
typedef struct ItemHandle
{
  uint64_t store_handle;
  uint64_t reclaim_handle;
  void *key;
  void *value; // 应该为store_handle 
}item_handle_t;
// zyh: 各store之间的关系,需要有个配置接口,多级关系主要有两种:包含cache和牺牲者cache,demote_level时在
// 原始level上仍然保留就是包含cache, 典型例子是cpu的l1,l2cache,否则就是牺牲者cache,既然把这类接口视为框架最基础的部分了,这部分
// 应该有个配置方式在这?

typedef enum
{
	SL_INCLUSIVE,
	SL_VICTI,
	// 其他一些也可以放在这
}sl_type_t;

class FrameworkAPI
{
  public:
    int get_store_level(const uint64_t store_handle, int64_t *level);
    int get_level_num(const int64_t *level_num);
    int get_level_percent(const int64_t level, int64_t *percent);
    int promote_level(const uint64_t store_handle);
    int demote_level(const uint64_t store_handle);
    int washout(const uint64_t store_handle);
    int set_store_level_type(const sl_type_t type);
};

////////////////////////////////////////////////////////////////////////////////////////////////////

// 下面是框架开发者需要实现的接口：

// 索引模块接口
// index模块存储key到ItemHandle的映射
// ItemHandle的内存由框架管理
class InterfaceIndex
{
  public:
    typedef void (*scan_callback_pt) (void *key, void *item_handle, void *args);
  public:
    virtual int put(void *key, void *item_handle) = 0;
    virtual int get(void *key, void **item_handle) = 0;
    virtual int erase(void *key) = 0;
    virtual int scan(scan_callback_pt callback, void *args) = 0;
};

// 替换算法接口
// reclaim为每个内存块分配唯一的handle
// 访问某个item时通过handle来通知access事件
class InterfaceReclaim
{
  public:
    virtual int assign(const uint64_t store_handle, InterfaceFramework *framework, uint64_t *reclaim_handle) = 0;
    virtual int access(const uint64_t reclaim_handle, InterfaceFramework *framework) = 0;
    virtual int reclaim(InterfaceFramework *framework) = 0;
};

// 存储引擎接口
// 存储cache中key-value的实体数据
// 要支持多级存储 实现操作多级存储的接口
// 其中ref_buffer为根据handle获取空间指针
// deref_buffer与ref_buffer配对使用 dirty表示指向的空间是否被修改过
// (注意：需要处理在reref_buffer之前free的情况)
class InterfaceStore
{
  public:
    virtual void *alloc(const int64_t nbyte, uint64_t *store_handle) = 0;
    virtual void free(const uint64_t store_handle) = 0;
    virtual void *ref_buffer(const uint64_t store_handle) = 0;
    virtual void deref_buffer(const uint64_t store_handle, const int dirty) = 0;

    virtual int get_store_level(const uint64_t store_handle, int64_t *level) = 0;
    virtual int get_level_num(const int64_t *level_num) = 0
    virtual int get_level_percent(const int64_t level, int64_t *percent) = 0;

    virtual int promote_level(const uint64_t store_handle) = 0;
    virtual int demote_level(const int64_t store_handle) = 0;
};







// 
// 我们试着写一个简单的hash实现，叫hash_index
// 首先需要细化框架为使用者提供的API, CacheAPI.put
InterfaceIndex		*hash_index;
InterfaceCacheUtils 	*utils;
InterfaceStore 		*store;
InterfaceReclaim	*reclaim;
InterfaceFramework	*framework;
int CacheAPI.put(void *key, void *value, const int overwrite_key, const int overwrite_value)
{
	int64_t hkey = 0;
	item_handle_t *ih = NULL;
	store_handle sh;
	
	ih = malloc(sizeof(item_handle_t)); // 这个应该不适用store接口吧?

	if (utils->copy_value) // 如果用户定义了copy_value表示他想深拷贝
	{
		store_handle tmp;
		store->alloc(utils->sizeof_value(value), tmp);
		utils->copy_value(value, tmp);
		ih->value = tmp;
	}
	else
	{
		ih->value = value;
	}
	

	ih->key = key;
	if (utils->hash_key)
		hkey = utils->hask_key(key);
	else
		hkey = default_hash_key(key);

	hash_index->put(&hkey, ih); // 这里存疑，是应该传heky还是key?
	// hash_index->put 见后边
	return 0;
}


typedef struct hash_body
{
	hash_body_t *next, *prev;
	item_handle_t item;

}hash_body_t

typedef struct hash_bucket_head
{
	hash_body_t *head, *tail;
	pthread_spinlock_t lock;
}hash_bucket_head_t

#define HASH_BUCKET_NR 100

hash_bucket_head hash_array[HASH_BUCKET_NR] = {0};

int hash_index.put(void *key, void *item_handle)
{
	int64_t hkey = (int64_t)*key;
	hash_bucket_head_t *head = NULL;

	hash_body_t *new_body = NULL;
	new_body = malloc(hash_body_t);
	new_body->item = item_handle;

	head = &hash_array[hkey];
	spin_lock(head->lock);
	new_body->prev = head->tail;
	new_body->next = head->head;
	head->head = new_body;
	spin_unlock(head->lock);

	reclaim->assign(item_handle->store_handle, framework,
			&item_handle->reclaim_handle);
}

